﻿using System;
using Trinity.Framework;
using Trinity.Framework.Helpers;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Controls;
using Trinity.Components.Combat;
using Trinity.Components.Combat.Resources;
using Trinity.DbProvider;
using Trinity.Framework.Actors.ActorTypes;
using Trinity.Framework.Avoidance.Structures;
using Trinity.Framework.Objects;
using Trinity.Framework.Reference;
using Trinity.Framework.Actors.Attributes;
using Trinity.UI;
using Trinity.Settings;
using Zeta.Common;
using Zeta.Game;
using Zeta.Game.Internals.Actors;


namespace Trinity.Routines.Wizard
{
    public sealed class FS_LightingArchonManald : WizardBase, IRoutine
    {
       
        #region Definition
		
        public string DisplayName => "法师塔/维 5+3，电疗，蛇疗";
        public string Description => "CDR 62+，星火，蛇杖，寅剑";
        public string Author => "太阳帝国";
        public string Version => "0.2";
        public string Url => "http://www.demonbuddy.cn/thread-11668-1-1.html";

        #region Build Definition
        public Build BuildRequirements =>  new Build
        {
            Sets = new Dictionary<Set, SetBonus>
            {
                { Sets.TalRashasElements, SetBonus.Third },
				{ Sets.VyrsAmazingArcana, SetBonus.Second }
            },
            Skills = new Dictionary<Skill, Rune>
            {
                { Skills.Wizard.Archon, null },     // 需要黑人技能
			},
            Items = new List<Item>
            {
                Legendary.ManaldHeal
            },
        };
		
        #endregion
        
		//public int BlackManStacks = Core.Buffs.GetBuffStacks(SNOPower.Wizard_Archon, -1);

			
		public override KiteMode KiteMode  => IsArchonActive ? KiteMode.Never : (KiteMode.Elites | KiteMode.Bosses);
        public override float KiteDistance => 25f;
		
        public override Func<bool> ShouldIgnoreAvoidance => () => Core.Rift.IsGreaterRift ? IsArchonActive : true ;
		//public override Func<bool> ShouldIgnoreKiting => () => Core.Rift.IsGreaterRift ? IsArchonActive : true;
		
        #endregion
		
		#region Methods
		protected override bool ShouldArchonTeleport(out Vector3 position)
        {
	
			
			position = Vector3.Zero;
            var skill = Skills.Wizard.ArchonTeleport;
			var affixOnPlayer = Core.Avoidance.InAvoidance(ZetaDia.Me.Position);
            var healthIsLow = Player.CurrentHealthPct < 0.7;
			var anyElitesinRange = TargetUtil.AnyElitesInRange(15f);
            var anyMobsInRange = TargetUtil.AnyMobsInRangeOfPosition(Player.Position, 20f, 4);
            

            if (!skill.CanCast())
				return false;

						
			if (affixOnPlayer||(healthIsLow && skill.TimeSinceUse > 1500.0))
            {
				
				Avoider.TryGetSafeSpot(out position, 30f,50f,ZetaDia.Me.Position,null);
					return true;
            }
            				
			if (anyElitesinRange && skill.TimeSinceUse > 2000.0)    
				
			{   
				
				
				if(Avoider.TryGetSafeSpot(out position, 30f,50f,ZetaDia.Me.Position,null))
					return true;
				
				if(TargetUtil.BestBuffPosition(50f, ZetaDia.Me.Position, false, out position) && Skills.Wizard.Archon.TimeSinceUse < 16000)
					return true;
			}
				
				
			if (CurrentTarget.IsBoss && CurrentTarget.Distance < 25f && skill.TimeSinceUse > 2000.0)  
				
			{   
				
				if(TargetUtil.BestBuffPosition(50f, CurrentTarget.Position, false, out position)&& Skills.Wizard.Archon.TimeSinceUse < 16000)
					return true;
				if(Avoider.TryGetSafeSpot(out position, 30f,50f,ZetaDia.Me.Position,null))
					return true;
			}
				
			if (anyMobsInRange && skill.TimeSinceUse > 2000.0  )    
			{   
				
				//if(TargetUtil.BestBuffPosition(50f, ZetaDia.Me.Position, false, out position)&& Skills.Wizard.Archon.TimeSinceUse < 16000)
				//	return true;
				Avoider.TryGetSafeSpot(out position, 30f,50f,ZetaDia.Me.Position,null);
					return true;
			}
				
				
			if (skill.TimeSinceUse > 3500.0)  
			{	
				
				Avoider.TryGetSafeSpot(out position, 30f,50f,ZetaDia.Me.Position,null);
					return true;
            }
				
			if (!Core.Buffs.HasInvulnerableShrine && Skills.Wizard.Archon.TimeSinceUse > 19500)  
			{	
				
				
                Avoider.TryGetSafeSpot(out position, 30f,50f,ZetaDia.Me.Position,null);
					return true;
            }	
			
			return position != Vector3.Zero;
        }

		 protected override bool ShouldTeleport(out Vector3 position)
        {
			
			
			position = Vector3.Zero;
            var skill = Skills.Wizard.Teleport;
            var affixOnPlayer = Core.Avoidance.InAvoidance(ZetaDia.Me.Position);
            var healthIsLow = Player.CurrentHealthPct < 0.7;            
            var anyElitesinRange = TargetUtil.AnyElitesInRange(15f);
            var anyMobsInRange = TargetUtil.AnyMobsInRangeOfPosition(Player.Position, 15f, 3);

            if (!skill.CanCast())
                return false;
			
			if (Player.IsInTown)
				return false;
			
            if (anyElitesinRange || anyMobsInRange || healthIsLow || affixOnPlayer)
            {
				
				Avoider.TryGetSafeSpot(out position, 30f, 50f, ZetaDia.Me.Position,null);
				return true;
            }

			
			Avoider.TryGetSafeSpot(out position, 30f, 50f, ZetaDia.Me.Position,null);
			    return position != Vector3.Zero;
        }
		
		private bool ShouldMovementTeleport(Vector3 destination)
        {

            if (!Skills.Wizard.Teleport.CanCast())
                return false;
			
			if (Player.IsInTown)
				return false;

            if (IsStuck || IsBlocked)
                return true;

            if (!CanTeleportTo(destination))
                return false;

            return true;
        }
		
		
		private bool ShouldMovementArchonTeleport(Vector3 destination)
        {

            if (!Skills.Wizard.ArchonTeleport.CanCast())
                return false;

            if (destination == Vector3.Zero)
                return false;

            if (IsStuck || IsBlocked)
                return true;

            var destinationDistance = destination.Distance(Core.Player.Position);
            if (destinationDistance < 15f && !PlayerMover.IsBlocked)
                return false;

            // Don't move into molten core/arcane.
            if (!Core.Avoidance.InCriticalAvoidance(ZetaDia.Me.Position) && Core.Avoidance.Grid.IsIntersectedByFlags(ZetaDia.Me.Position, destination, AvoidanceFlags.CriticalAvoidance))
                return false;

            if (Skills.Wizard.Teleport.TimeSinceUse < 200)
                return false;

            return true;
        }

		
		#endregion

        public TrinityPower GetOffensivePower()   //战斗函数，战斗分黑人，白人阶段
        {
			//Core.Logger.Log(LogCategory.Routine, $"在 offensivePower 中");
            Vector3 position = Vector3.Zero;
			IEnumerable<TrinityActor> clusters = TargetUtil.GetBestClusterUnits(15f,65f,true,true,false,false);
			TrinityActor target = (from u in clusters
									where !u.IsInvulnerable
									select u).FirstOrDefault() ?? CurrentTarget;
			
			bool IsHealthVeryLow = Player.CurrentHealthPct < Settings.SuperEmergencyHealthPct;
			
			if (IsArchonActive)// 黑人阶段
			{
				
				
				if (ShouldArchonTeleport(out position) && position!=Vector3.Zero && CanTeleportTo(position))
				{
					
					return Teleport(position);
				}
				// 黑人不传送则进行攻击目标
                if (Skills.Wizard.ArchonDisintegrationWave.CanCast()&& target !=null )
				{
					//Core.Logger.Log(LogCategory.Routine, $"不需要传送--攻击目标");
					return ArchonDisintegrationWave(target);
				}
				// 以上条件都不满足的话，向旁边走7码，尝试解除卡位
				return null;
			}
			
			if (!IsArchonActive)  //白人阶段
			{
				
				//Avoider.TryGetSafeSpot(out position, 30f, 50f, ZetaDia.Me.Position,null);
				
				if (Skills.Wizard.Archon.CanCast())//能变黑人
				{
					if (HasTalRashaStacks||IsHealthVeryLow )
						return Archon();
				}
				// 下面是不能变黑人--刷黄道
				
				if (ShouldTeleport(out position))
				{
					//Core.Logger.Log(LogCategory.Routine, $"白人传送");
						return Teleport(position);	
				}
				
			
				if(Core.Avoidance.InAvoidance(ZetaDia.Me.Position) && !Skills.Wizard.ArchonTeleport.CanCast())
				{
					return Walk(Avoider.SafeSpot);
				}
				if (Skills.Wizard.Hydra.CanCast() && Player.Summons.HydraCount < MaxHydras && IsInCombat )
				{
					//Core.Logger.Log(LogCategory.Routine, $"蛇数量不满,放蛇");
					return Hydra(target.Position);
				}
				
				if (Skills.Wizard.RayOfFrost.CanCast() && Player.PrimaryResource > 30.0)
				{
					//Core.Logger.Log(LogCategory.Routine, $"使用冰霜射线");
					return RayOfFrost(target);
				}
					
				if (Skills.Wizard.Blizzard.CanCast() && Player.PrimaryResource > 36.0 && Skills.Wizard.Blizzard.TimeSinceUse > 5000.0)  
				{
					//Core.Logger.Log(LogCategory.Routine, $"使用暴风雪");
					return Blizzard(target);
				}

				if (Skills.Wizard.EnergyTwister.CanCast()&& Player.PrimaryResource > 33.0 && Skills.Wizard.EnergyTwister.TimeSinceUse > 5000.0)
               
				{
					//Core.Logger.Log(LogCategory.Routine, $"使用能量气旋");
					return EnergyTwister(target);
				}		   
    
				if (Skills.Wizard.BlackHole.CanCast() && Player.PrimaryResource > 16.0 && Skills.Wizard.BlackHole.TimeSinceUse > 3000.0)
				{
					//Core.Logger.Log(LogCategory.Routine, $"使用黑洞:{CurrentTarget}");
					return BlackHole(target);
				}
				
				if (Skills.Wizard.ArcaneTorrent.CanCast() && Player.PrimaryResource > 40.0 )  
				{
					//Core.Logger.Log(LogCategory.Routine, $"静电放射:{CurrentTarget}");
					return ArcaneTorrent(target);
					
				}
				
			}
			
			return Walk(Avoider.SafeSpot, 7f);  
		}

         public TrinityPower GetDefensivePower()
        {
			//Core.Logger.Log(LogCategory.Routine, $"在 defensivePower 中");
            return null;
        }

        public TrinityPower GetBuffPower()  
        {
			
			//Core.Logger.Log(LogCategory.Routine, $"在 buffPower 中");
			bool IsHealthVeryLow = Player.CurrentHealthPct < Settings.SuperEmergencyHealthPct;
			
            if (!IsArchonActive)  
			{   
		        if (!Skills.Wizard.EnergyArmor.IsBuffActive && Skills.Wizard.EnergyArmor.CanCast())
				{
					return EnergyArmor();
				}
				if (!Skills.Wizard.MagicWeapon.IsBuffActive && Skills.Wizard.MagicWeapon.CanCast())
				{
					return MagicWeapon();
				}
				if (Skills.Wizard.Archon.CanCast() && !Player.IsInTown &&( HasTalRashaStacks || IsHealthVeryLow))
				{
					return Archon();
				}
			}				
			else
			{
			   if (!IsArchonSlowTimeActive && Skills.Wizard.ArchonSlowTime.CanCast())	
			   {
				   return ArchonSlowTime();
			   }
			   if (Player.IsMoving && Skills.Wizard.ArchonBlast.CanCast())
			   {
				   return ArchonBlast();
			   }
			   
			}
			return null; 
        }

        public TrinityPower GetDestructiblePower()  // 可破坏物体的技能释放
        {
			//  黑人用爆炸，白人用冰霜射线 破坏物体
			//Core.Logger.Log(LogCategory.Routine, $"在 destructiblePower 中");
			
						
            if (IsArchonActive)  
			{
				if (Skills.Wizard.ArchonBlast.CanCast() && CurrentTarget!= null && CurrentTarget.Distance <15f )  
				{
					return ArchonBlast();
				}
			}
			
			else if (Skills.Wizard.RayOfFrost.CanCast() && CurrentTarget!= null &&  CurrentTarget.Distance <40f && CurrentTarget.IsInLineOfSight)
			{
				return RayOfFrost(CurrentTarget);
			}
			else if (Skills.Wizard.ArcaneTorrent.CanCast() && CurrentTarget!= null &&  CurrentTarget.Distance <15f && CurrentTarget.IsInLineOfSight)
			{
				return ArcaneTorrent(CurrentTarget);
			}
			
			return DefaultDestructiblePower();
        }

		
        public TrinityPower GetMovementPower(Vector3 destination)// 用黑人传送和传送赶路，否则走路
        {
			
			
		//	Core.Logger.Log(LogCategory.Routine, $"在 MovementPower 中");
            if (CanTeleport	&& destination.Distance(Player.Position) > 15f 
					&& !Core.Avoidance.InCriticalAvoidance(destination)&& !Player.IsInTown)
			{
				//Core.Logger.Log(LogCategory.Routine, $"在 MovementPower 中传送");
				if(destination!= Vector3.Zero)
					return Teleport(destination);
			}
			

            if (IsStuck || IsBlocked)
            {
				//Core.Logger.Log(LogCategory.Routine, $"卡住了");
				var temptarget = TargetUtil.GetClosestUnit(15f) ?? CurrentTarget;
				if(CanTeleport)
				{
					//Core.Logger.Log(LogCategory.Routine, $"卡住了，传送");
						return Teleport(destination);
				}
				
				else return Walk(destination,10f); 
			
				
				/*	if (Skills.Wizard.ArchonDisintegrationWave.CanCast()  )
					//	return ArchonDisintegrationWave(temptarget);
					
				//	if (Skills.Wizard.RayOfFrost.CanCast() &&  Skills.Wizard.RayOfFrost.TimeSinceUse > 1200.0)
					//	return RayOfFrost(temptarget);
					
					if (Skills.Wizard.Blizzard.CanCast() &&  Skills.Wizard.Blizzard.TimeSinceUse > 1200.0)  
						return Blizzard(temptarget);
								
					if (Skills.Wizard.BlackHole.CanCast() &&  Skills.Wizard.BlackHole.TimeSinceUse > 1200.0)
						return BlackHole(temptarget);
					
					if (Skills.Wizard.EnergyTwister.CanCast() &&  Skills.Wizard.EnergyTwister.TimeSinceUse > 1200.0)
				        return EnergyTwister(temptarget);
					
					if (Skills.Wizard.ArcaneTorrent.CanCast()&& Skills.Wizard.ArcaneTorrent.TimeSinceUse > 1200.0)  
						return ArcaneTorrent(temptarget);
				*/
				
            }
			
						
			return Walk(destination,10f); 
			
        }


        #region Settings
        
        public override int ClusterSize => IsArchonActive ? Settings.ClusterSize : 3; 
		//public override int KiteStutterDelay =>	1000 ;
		//public override int KiteStutterDuration => 1500;
        public override float EmergencyHealthPct => Settings.EmergencyHealthPct;
		
		public float SuperEmergencyHealthPct => Settings.SuperEmergencyHealthPct;
		
        IDynamicSetting IRoutine.RoutineSettings => Settings;
        public FS_LightingArchonManaldSettings Settings { get; } = new FS_LightingArchonManaldSettings();

        public sealed class FS_LightingArchonManaldSettings : NotifyBase, IDynamicSetting
        {
            private SkillSettings _teleport;
            private int _clusterSize;
            private float _emergencyHealthPct;
			private float _superEmergencyHealthPct;

            [DefaultValue(6)]
            public int ClusterSize
            {
                get { return _clusterSize; }
                set { SetField(ref _clusterSize, value); }
            }

            [DefaultValue(0.6f)]
            public float EmergencyHealthPct
            {
                get { return _emergencyHealthPct; }
                set { SetField(ref _emergencyHealthPct, value); }
            }

			[DefaultValue(0.2f)]
            public float SuperEmergencyHealthPct
            {
                get { return _superEmergencyHealthPct; }
                set { SetField(ref _superEmergencyHealthPct, value); }
            }
			
            public SkillSettings Teleport
            {
                get { return _teleport; }
                set { SetField(ref _teleport, value); }
            }

            #region Skill Defaults

            private static readonly SkillSettings TeleportDefaults = new SkillSettings
            {
                UseMode = UseTime.Default,
                RecastDelayMs = 200,
                Reasons = UseReasons.Blocked
            };

            #endregion

            public override void LoadDefaults()
            {
                base.LoadDefaults();
                Teleport = TeleportDefaults.Clone();
            }

            #region IDynamicSetting

            public string GetName() => GetType().Name;
            public UserControl GetControl() => UILoader.LoadXamlByFileName<UserControl>(GetName() + ".xaml");
            public object GetDataContext() => this;
            public string GetCode() => JsonSerializer.Serialize(this);
            public void ApplyCode(string code) => JsonSerializer.Deserialize(code, this, true);
            public void Reset() => LoadDefaults();
            public void Save() { }

            #endregion
        }

        #endregion
    }
}


